package com.chenjun.designpattern.behavior.observer;

import java.util.HashSet;
import java.util.Set;

/**
 * <p>
 * 【观察者模式】有时被称作发布/订阅模式，观察者模式定义了一种一对多的依赖关系，
 * 让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时，会通知所有观察者对象，使它们能够自动更新自己。
 * </p>
 * <p>
 * ●（一） 抽象主题(Subject)角色：抽象主题角色把所有观察者对象的引用保存在一个聚集（比如ArrayList/HashSet对象）里，
 * 每个主题都可以有任何数量的观察者。抽象主题提供一个接口，可以增加和删除观察者对象，抽象主题角色又叫做抽象被观察者(Observable)角色。
 * </p>
 * <p>
 * ●（二） 具体主题(ConcreteSubject)角色：将有关状态存入具体观察者对象；在具体主题的内部状态改变时，
 * 给所有登记过的观察者发出通知。具体主题角色又叫做具体被观察者(Concrete Observable)角色。
 * </p>
 * <p>
 * ●（三） 抽象观察者(Observer)角色：为所有的具体观察者定义一个接口，在得到主题的通知时更新自己，这个接口叫做更新接口。
 * </p>
 * <p>
 * ●（四） 具体观察者(ConcreteObserver)角色：存储与主题的状态自恰的状态。具体观察者角色实现抽象观察者角色所要求的更新接口，
 * 以便使本身的状态与主题的状态 像协调。如果需要，具体观察者角色可以保持一个指向具体主题对象的引用。
 * </p>
 * 我的总结：多个观察者在观察一个主题， 他就住在主题对象里面，以集合形式存在，当主题更新时，能遍历集合对所有观察者进行某种操作
 * 
 * <p>推模型
 * @author Administrator
 *
 */
public class 观察者模式
{
	public static void main(String[] args)
	{
		//创建主题对象
        ConcreteSubject subject = new ConcreteSubject();
        //创建观察者对象1
        AbstractObser observer1 = new ConcreteObserver();
        //创建观察者对象2
        AbstractObser observer2 = new ConcreteObserver();
        //创建观察者对象3
        AbstractObser observer3 = new ConcreteObserver();
        
        //将观察者对象登记到主题对象上
        subject.addOb(observer1);
        subject.addOb(observer2);
        subject.addOb(observer3);
        
       //改变主题对象的状态
        subject.change("new-state");
	}
}

abstract class AbstractSubject
{
	protected Set<AbstractObser> obSet = new HashSet<AbstractObser>();

	public boolean addOb(AbstractObser ob)
	{
		System.out.println("添加一个观察者");
		return obSet.add(ob);
	}

	public boolean removeOb(AbstractObser ob)
	{
		System.out.println("移除一个观察者");
		return obSet.remove(ob);
	}

	public void nodifyObservers(String newState)
	{
		for (AbstractObser item : obSet)
		{
			item.update(newState);
		}
	}
}

class ConcreteSubject extends AbstractSubject
{
	private String state;

	/**
	 * 重写父类的通知行为
	 */
	public void change(String newState)
	{
		state = newState;
		System.out.println("主题状态为：" + state);
		//状态发生改变，通知各个观察者
        this.nodifyObservers(state);
	}

	/**
	 * getter and setter
	 * 
	 * @return
	 */
	public String getState()
	{
		return state;
	}

	public void setState(String state)
	{
		this.state = state;
	}
}

/**
 * 抽象观察者
 * 
 * @author Administrator
 *
 */
abstract class AbstractObser
{
	public abstract void update(String newState);
}

/**
 * 具体观察者
 * 
 * @author Administrator
 *
 */
class ConcreteObserver extends AbstractObser
{
	private String observerState;
	
	@Override
	public void update(String newState)
	{
		observerState = newState;
		System.out.println(this+"的状态为："+observerState);
	}
}
